#include "BigInteger.h"
#include "WaterCalc.h"
#include "SList.h"
#include "SListVec.h"
#include "FixedList.h"
#include <list>
#include <cassert>

//void WaterCalcTest(int argc, char* argv)
//{
//	 std::cout << "Main\n";
//	 //const char *file const = "dad";
//	 WaterCalculator c = WaterCalculator();//file);
//	 try {
//		c.ParseMatrixFile();
//		c.printMatrix();
//		std::cerr << std::endl;
//		c.Volume();
//	 }catch (ParseMatrixException e){
//		std::cerr << "Error parsing file: \n";
//	 }
//	 
//}

void BigIntegerTest()
{
	unsigned int MaxUint = std::numeric_limits<unsigned int>::max();
	std::string st("1432424567576576576576576576576556");
	BigInteger uffa(st.c_str());
	std::string uffa_str = uffa.asString();
	std::cout << uffa_str << std::endl;
	std::cout << st << std::endl;

//#define MODULE_TEST
#ifdef MODULE_TEST

#define A 454433423
#define B -353432
	BigInteger a(A);
	BigInteger b(B);

	a%=b;
	a.PrintBinary();
	BigInteger exp(A % B);
	exp.PrintBinary();
	int posA = 5;
	int negA = -5;
	int posB = 2;
	int negB = -2;

	std::cout << posA % posB << std::endl;
	std::cout << posA % negB << std::endl;
	std::cout << negA % posB << std::endl;
	std::cout << negA % negB << std::endl;
#endif
//#define SUB_TEST
#ifdef SUB_TEST
	BigInteger first(10);
	//BigInteger exp(4);
	
	first -= 4;

	BigInteger exp(6);

	first.PrintBinary();
	std::cout << "most significant bit pos : " << first.MostSignificantBitIndex() << std::endl;

	exp.PrintBinary();
	std::cout << "most significant bit pos : " << exp.MostSignificantBitIndex() << std::endl;
	
#endif
//#define BITWISE_TEST OK
#ifdef BITWISE_TEST
	BigInteger first (535345231);
	first <<= 32;
	first += 4324233;
	first <<= 32;
	first += 4324233;
	
	first.PrintBinary();

	BigInteger second(MaxUint);
	second <<=32;
	second += MaxUint;
//	second <<=32;
//	second += MaxUint;
	second.PrintBinary();

	BigInteger xor =  second ^ first ;
	xor.PrintBinary();
	std::cout << xor.MostSignificantSlice << std::endl;
	BigInteger or = first | second;
	or.PrintBinary();
	std::cout << or.MostSignificantSlice << std::endl;
	BigInteger and = first & second;
	and.PrintBinary();
	std::cout << and.MostSignificantSlice << std::endl;

	BigInteger test = -10;
	test<<=45 ;
	test.PrintBinary();
	std::cout << "most significant bit pos : " << test.MostSignificantBitIndex() << std::endl;
#endif

//#define STRING_TEST
//#define STRING_TEST
#ifdef STRING_TEST

//	"432424234234234234324213576876843243242432432423423423423423522255" / 2 -> crash
//#define FF
#ifdef FF
	BigInteger a (22);
	//BigInteger a ("4324242342345434534253545435345245342235345");
//	a <<= 18 * 2;
	a += 37;
	BigInteger exp = a;
		exp >>=1;
		a/=2;
		if (exp == a ){
			std::cout << "ok " <<std::endl;
		}else{
			std::cout << "wrong "  <<std::endl;
		}

//		BigInteger a (0);
		BigInteger one(1);
		int i = 0;
		BigInteger sh1;// = one << 65;
		one.PrintBinary();
		for (int i = 0 ;i < 100 ; ++i){
			sh1 = one << i;
			sh1.PrintBinary();
		}
		BigInteger sh2 = one << 66;
		
		one.PrintBinary();
		sh1.PrintBinary();
		sh2.PrintBinary();

		BigInteger foo(4324324);
		BigInteger bar(43);
		BigInteger res = foo / bar;
		BigInteger shouldBe = 4324324 / 43;
		res.PrintBinary();
		shouldBe.PrintBinary();
#endif

BigInteger a ("4324242342345434534253545435345245342235345");
BigInteger fract = a;
BigInteger div = a >> 1;
BigInteger b("-43434116576548769870987");
a /= b;

a.PrintBinary();
div.PrintBinary();


for (int i = 22 ; i < 10000000 ; ++i)
{	

			
		BigInteger a = 1; 
	a <<= i * 3  ;
	a.PrintBinary();
	a +=37;
	a.PrintBinary();
//	a <<= i ;
	//a+=37;
	BigInteger exp = a;
//	exp >>=1;
//	a.PrintBinary();
	//BigInteger sedici("16");
//	sedici /= 2;
	//sedici.PrintBinary();
	
	
	while (a > 0){

		exp >>=1;
		a/=2;
		a.PrintBinary();
		exp.PrintBinary();
		if (exp == a ){
		//	std::cout << "ok " <<std::endl;
		}else{
			std::cout << "wrong " << i  <<std::endl;
		}
	}
}


#endif
	//#define ASSIGNMENT
#ifdef ASSIGNMENT
	BigInteger original (-32423424);
	BigInteger ass = original;

	original.PrintBinary();
	ass.PrintBinary();
#endif
//#define SUM_TEST
#ifdef SUM_TEST
unsigned int MaxUint = std::numeric_limits<unsigned int>::max();
	
#define A MaxUint
#define B 432442342
#define F 15
#define G 10
BigInteger f(F);
BigInteger g(G);

f -= g;
BigInteger ex(F - G);

f.PrintBinary();
ex.PrintBinary();

	BigInteger a(MaxUint);
	BigInteger b(1);
	a.PrintBinary();
	a += b;

//	BigInteger exp(A + B);
	a.PrintBinary();

	a += 4324324;
	a.PrintBinary();
	a+= MaxUint;
	a.PrintBinary();

#define D 50
#define C (-4)
	BigInteger c(C);
	BigInteger d(D);

	c+= d;
	BigInteger exp(46);
	c.PrintBinary();
	exp.PrintBinary();
#endif
//#define MULTIPLICATION_TEST seems to work
#ifdef MULTIPLICATION_TEST
unsigned int MaxUint = std::numeric_limits<unsigned int>::max();
#define A MaxUint
#define B 1

#define F 342324
#define S -253543
BigInteger first (F);
BigInteger sec (S);

first.PrintBinary();
std::cout << first.MostSignificantSlice << "\n";
sec.PrintBinary();
std::cout << sec.MostSignificantSlice << "\n";

first *= sec;
first.PrintBinary();
std::cout << first.MostSignificantSlice << "\n";

BigInteger e((F* S));
e.PrintBinary();
std::cout << e.MostSignificantSlice << "\n";


BigInteger uno (1);
BigInteger menouno = -uno;
uno.PrintBinary();
std::cout << uno.MostSignificantSlice << "\n";

menouno.PrintBinary ();
std::cout << menouno.MostSignificantSlice << "\n";

BigInteger prod (5);
prod.PrintBinary ();
std::cout << prod.MostSignificantSlice << "\n";

prod *= uno;
prod.PrintBinary ();
std::cout << prod.MostSignificantSlice << "\n";

prod *= menouno;
prod.PrintBinary ();
std::cout << prod.MostSignificantSlice << "\n";

BigInteger shouldBe (-5);
shouldBe.PrintBinary ();
std::cout << shouldBe.MostSignificantSlice << "\n";


BigInteger a(MaxUint );
	BigInteger b(B);
	a.PrintBinary();
	b.PrintBinary();
	/*a.PrintBinary();
	std::cout << a.MostSignificantSlice << "\n";
	a +=1 ;
	a.PrintBinary();
	std::cout << a.MostSignificantSlice << "\n";
	*/
	
	a *= b;
	//BigInteger exp();
	a.PrintBinary();
	BigInteger c = -a;
	c.PrintBinary();
//	exp.PrintBinary();
#endif



//#define ETHIOPIAN_TEST OK
#ifdef ETHIOPIAN_TEST
#define A (-268768)
#define B 4564443
	BigInteger a(A);
	BigInteger b(B);
	
	if (a >= b)
	{
		int foo = 5;
	}
	//BigInteger c(453453);
	//for (int i = 0 ; i < 30 ; ++i){
	//	c.PrintBinary();
	//	c >>= 1;
	//}

	BigInteger res = EthiopianMultiplication(a,b);
	res.PrintBinary();
	BigInteger res2 = EthiopianMultiplication(b,a);
	res2.PrintBinary();
	std::cout << "expected" <<std::endl;
	BigInteger exp(A * B);
	exp.PrintBinary();
#endif
//#define SHIFT_TEST //BUG with defaultslice 5 and shift left-right 96
#ifdef SHIFT_TEST
	
	//unsigned int MaxUint = std::numeric_limits<unsigned int>::max();

	BigInteger one (1);
	one <<= 92;

	while (one > 0){
	
		BigInteger div = one / 2;
		one >>= 1;
		if (div != one ){
			std::cout << "wrong"   << std::endl;
			
		}
		div.PrintBinary();
	}

	one = 1;
	one <<= 96;
	one.PrintBinary();
	one >>= 32;
	one.PrintBinary();
	while (one > 0){
		one >>= 1;
		one.PrintBinary();
	
	}
	unsigned int z = 10;
	std::cout << z << std::endl;
	std::cout << (z << 32) << std::endl;
	
	BigInteger foo(13);
	foo.PrintBinary();
	std::cout << "slice most "  << foo.MostSignificantSlice << std::endl;
	foo <<= 32;
	foo.PrintBinary();
	std::cout << "slice most "  << foo.MostSignificantSlice << std::endl;
	foo >>= 32;
	foo.PrintBinary();
	std::cout << "slice most "  << foo.MostSignificantSlice << std::endl;
	

	foo <<= 64;
	foo.PrintBinary();
	std::cout << "slice most "  << foo.MostSignificantSlice << std::endl;
	foo >>= 64;
	foo.PrintBinary();
	std::cout << "slice most "  << foo.MostSignificantSlice << std::endl;
	
	foo <<= 96;
	foo.PrintBinary();
	std::cout << "slice most "  << foo.MostSignificantSlice << std::endl;
	foo >>= 96;
	foo.PrintBinary();
	std::cout << "slice most "  << foo.MostSignificantSlice << std::endl;
	
	for (int i = 0 ; i < 50 ; i++){
		foo <<= 1;
		foo.PrintBinary();
		std::cout << "slice most "  << foo.MostSignificantSlice << std::endl;
	
	}
	BigInteger a(-15 );
	a.PrintBinary();
	BigInteger exp ((-15) >> 1);
	//a <<= 32;
	int x = -1;
	std::cout << x << std::endl;
	std::cout << (x >> 1) << std::endl;
	a >>=1;
	a.PrintBinary();
	exp.PrintBinary();
	//for (int i = 0 ; i < 50 ; i++){
//		a <<= 1;
//		a.PrintBinary();
	
//	}
	for (int i = 0 ; i < 50 ; i++){
		a >>= 1;
		a.PrintBinary();
	
	}
	//exp.PrintBinary();
#endif 
#define DIVISION_TEST
#ifdef DIVISION_TEST

#define MAX_DIVIDEND 20000
#define MAX_DIVISOR 20000
	BigInteger aa(MaxUint);
	for (int i = 7 ;  i< MAX_DIVIDEND ; ++i){
		aa +=1 ;
		for (int j = 2 ; j <= aa ; ++j ){
			
			
			BigInteger multiplied = aa * j;
			BigInteger divided = multiplied / j;
			BigInteger rest = multiplied % j;
			if (multiplied != (divided + rest)){
				std::cout << "houston we got a prob!" << std::endl;
	
			}else{
				std::cout << "OK: i " << i << " j " << j <<   std::endl;
			}
		}
	}

	BigInteger fo(15);
	BigInteger due(-2);
	BigInteger rs = fo / due;
	rs.PrintBinary();
	BigInteger a(23232);
	BigInteger b(-3);
	BigInteger res = a/b;

	res.PrintBinary();
	std::cout << "expected \n" ;

	BigInteger foo(23232 / (-3));
	foo.PrintBinary();
#endif
	/*BigInteger a (-19);
	BigInteger b(12);
	BigInteger c(12);*/
	
	/*BigInteger r1 = a % b;
	BigInteger r2 = c % b;
	r1.PrintBinary();
	BigInteger exp1(((-19) % 12));
	std::cout << "expected \n" ;
	exp1.PrintBinary();

	r2.PrintBinary();
	BigInteger exp2((19 % 12));
	std::cout << "expected \n" ;
	exp2.PrintBinary();*/

//#define DIVISION_TEST OK
#ifdef DIVISION_TEST

#define A -12
#define B -2


	BigInteger sette (A);
	BigInteger divisor(B);
	
	sette /= divisor;
	sette.PrintBinary();
	BigInteger shouldBe(A / B);
	shouldBe.PrintBinary();

	sette <<=32;
	sette.PrintBinary();
	sette += 42342;
	sette.PrintBinary();
	BigInteger xxx = sette / divisor;
	sette /= divisor;

	sette.PrintBinary();
	xxx.PrintBinary();
	//shouldBe(A / B);
	shouldBe.PrintBinary();

	BigInteger maxx(MaxUint);
	maxx <<=31;

	maxx.PrintBinary();

	while(true){
		maxx /= 2; //bug: divisor power become negative with 2 slices filled..
		maxx.PrintBinary();
	}
	sette /= divisor;
	sette.PrintBinary();
	BigInteger foobar (A /B);
	foobar.PrintBinary();

//	BigInteger due(B);
	BigInteger quo = sette / due;
	quo.PrintBinary();
	BigInteger exp(A/B);
	exp.PrintBinary();
#define XX (-19)

	
//	BigInteger a(XX);
	BigInteger mod1 = a % 4;
	mod1.PrintBinary();
	std::cout << "expected "  << std::endl;
	int mo = (XX) % 4;
	BigInteger mod2(mo);
	mod2.PrintBinary();
	
//	BigInteger res = a / (-3);

	res.PrintBinary();
	std::cout << "expected "  << std::endl;
	BigInteger r((XX/ (-3)));
	r.PrintBinary();

#endif
//#define COMPARISON_TEST seems to work
#ifdef COMPARISON_TEST
	BigInteger a(35054);
	BigInteger b(16);
	BigInteger c(-16);

	if (a < b)
		std::cout << "> works";
	if (b <= a)
		std::cout << "> works";
	if (! (a <= b))
		std::cout << "> works";
	if (c <= b)
		std::cout << "> works";
	if (c > b)
		std::cout << "> works";
#endif
	/*int x = 10;
	x = x << 31;
	BigInteger i = BigInteger();
//	i.PrintBinary();
//
//	BigInteger nove = BigInteger(9);
//	nove.PrintBinary();
//	*/
//	BigInteger n = BigInteger(0xFFFFFFFF);
////	n<<= 31;
//	n.PrintBinary();
//
//	BigInteger uno = BigInteger(1);
//	BigInteger copy = ~n;
//	n += uno;
//	n.PrintBinary();
//
//
//	//copy constructor test
//
//	
//	copy.PrintBinary();
//	copy = n;
#ifdef TEST_SEGNO

	if (copy.isPositive()){
		std::cout << "copy positive";
	}else{
		std::cout << "copy negative";
	}
	if (uno.isPositive()){
		std::cout << "uno positive";
	}else{
		std::cout << "uno negative";
	}
#endif

#ifdef TEST_SUM
	BigInteger a(36);
	BigInteger b(13);
	std::cout << "36\n";
	a.PrintBinary();
	a += 0;
	a.PrintBinary();
	
	std::cout << "13\n";
	b.PrintBinary();
	BigInteger d(-13);
	std::cout << "meno 13\n";
	d.PrintBinary();

	
	BigInteger r1 = a;
	BigInteger r2 = d;
	r1 += d;
	r1.PrintBinary();
	r2 += a;
	r2.PrintBinary();


	BigInteger e = b;
	e.complement();
	std::cout << "complement 13\n";
	e.PrintBinary();
	
	
	BigInteger c(36 - 13);
	std::cout << "23\n";
	c.PrintBinary();

	std::cout << "36 -= 13\n";
	BigInteger aux = a;
	aux -= b;
	aux.PrintBinary();

	
	std::cout << " -13 +36 \n";
	BigInteger aux2 =  (-13) + a;
	aux2.PrintBinary();

	BigInteger res = a - b;
	res.PrintBinary();
#endif

	/*BigInteger c(-13);
	c.PrintBinary();

	BigInteger foo (45);
	foo -=(5);
	foo.PrintBinary();
	BigInteger quar(40);
	quar.PrintBinary();
	BigInteger res1 = a + c;
	BigInteger res2 = a - b;
	res1.PrintBinary();
	res2.PrintBinary();*/

	/*
	BigInteger dieci(10);
	BigInteger cinque(-5);

	BigInteger r = dieci + cinque;
	dieci.PrintBinary();
	cinque.PrintBinary();
	r.PrintBinary();
	a = a - b;
	a.PrintBinary();*/
	
	//BigInteger exp(36 - 13);
	//exp.PrintBinary();

	//unsigned int MaxUint = std::numeric_limits<unsigned int>::max();

	//BigInteger max(MaxUint);
	//max.PrintBinary();
	//max *= 2;
	//max.PrintBinary();
	//BigInteger quattro(4);
	//std::cout << "tre\n";
	//tre.PrintBinary();
	//std::cout << "quattro\n";
	//quattro.PrintBinary();
	//std::cout << "3 x 4\n";
	//tre *= 4;
	//tre.PrintBinary();
	//BigInteger res = tre + quattro;
	//res.PrintBinary();

	//n <<= 31;//.shiftLeft(32);
	//n.PrintBinary();
	//n <<= 1;//.shiftLeft(32);
	//n.PrintBinary();
	//n <<= 1;//.shiftLeft(32);
	//n.PrintBinary();
	//for (int i = 0 ; i < 32; ++i){
	//	n <<= 1;//.shiftLeft(32);
	//	n.PrintBinary();
	//}

}
void SListTest(){
	using namespace unstd;
	std::list<int> l = std::list<int>() ;
	SList<int> sl = SList<int>();
	std::cout << "list size : " << l.max_size() << "\n";
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "error: list should be empty\n";
	}
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "error: SList should be empty\n";
	}
	for (int i = 0 ; i < 4; ++i){
		l.push_back(i);
		sl.push_back(i);
	}
	std::cout << "list size : " << l.size() << "\n";
	std::cout << "list size : " << sl.size() << "\n";
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (int i = 0 ; i < 4; ++i){
		l.push_front(i * 3);
		sl.push_front(i * 3);
	}
	std::cout << "list size : " << l.size() << "\n";
	std::cout << "list size : " << sl.size() << "\n";
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator first = l.begin();
	++first;
	SList<int>::iterator firstl = sl.begin();
	++firstl;

	
	l.erase(first);
	sl.erase(firstl);
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	for (int i = 0 ; i < 4; ++i){
		l.push_front(i * 15);
		sl.push_front(i * 15);
	}
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (int i = 0 ; i < 3; ++i){
		sl.pop_back();
		l.pop_back();
	}
		std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator l_it = l.begin();
	++l_it;++l_it;++l_it;
	SList<int>::iterator sl_it = sl.begin();
	++sl_it;++sl_it;++sl_it;
	
	while (l_it != l.end() ){
		l_it = l.erase(l_it);
	
	}
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	while (sl_it != sl.end() ){
		sl_it = sl.erase(sl_it);//bug here: ..tail pointer is messed up
	
	}
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	l.erase(l_it, l.end());
	sl.erase(sl_it, sl.end());

	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator it_second_place = l.begin();
	++it_second_place;
	++it_second_place;
	int n = 5;
	for (int i = 0 ; i < n; ++i){
		it_second_place = l.insert(it_second_place,i);
	}
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	SList<int>::iterator it_sl_second_place = sl.begin();
	++it_sl_second_place;
	++it_sl_second_place;
	for (int i = 0 ; i < n; ++i){
		it_sl_second_place = sl.insert(it_sl_second_place,i);
	}
	
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator it_third_place = l.begin();
	++it_third_place;
	++it_third_place;
	//n = 5;
	
	l.insert(it_third_place,4,19);
	
	SList<int>::iterator it_sl_third_place = sl.begin();
	++it_sl_third_place;
	++it_sl_third_place;

	sl.insert(it_sl_third_place,(SList<int>::size_type)4,19);
	
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	for (int i = 0 ; i < 3; ++i){
		sl.pop_back();
		l.pop_back();
	}

	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
//	for (SList<int>::iterator it = )
	std::list<int>::iterator ret1 = l.insert(l.end(), 37);
	auto ret2 = sl.insert(sl.end(), 37);

	l.insert(ret1, 39);
	sl.insert(ret2,39);
	
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
}

void SListInterfaceTest()
{
	using namespace unstd;
	
	SList<int> s_list = SList<int>();
	std::list<int> std_list = std::list<int>();
	
	for (int i = 0 ; i < 7; ++i){
		s_list.push_back(10 * i);
		std_list.push_back(10 * i);
	}
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = std_list.begin() ; it != std_list.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = s_list.begin() ; it != s_list.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	int s_front = s_list.front();
	int std_front = std_list.front();
	
	for (int i = 0 ; i < 7; ++i){
		s_list.pop_back();
		std_list.pop_back();

		std::cout << "------------------------------" << std::endl;
		for (std::list<int>::iterator it = std_list.begin() ; it != std_list.end(); ++it){
			std::cout << "val " << *it << std::endl;
		}
		std::cout << "------------------------------" << std::endl;
		for (SList<int>::iterator it = s_list.begin() ; it != s_list.end(); ++it){
			std::cout << "val " << *it << std::endl;
		}
	}
	for (int i = 0 ; i < 7; ++i){
		s_list.push_front(10 * i);
		std_list.push_front(10 * i);
	}
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = std_list.begin() ; it != std_list.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = s_list.begin() ; it != s_list.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	//std::list<int>::iterator it2 = std_list.begin() ;
	while(std_list.begin() != std_list.end()){
		std_list.pop_front();
	}
	//SList<int>::iterator it = s_list.begin() ;
	while(s_list.begin() != s_list.end()){
		s_list.pop_front();
	}
		std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = std_list.begin() ; it != std_list.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SList<int>::iterator it = s_list.begin() ; it != s_list.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	//TODO const front


}
void FixedListTest()
{
	using namespace unstd;
	std::list<int> l = std::list<int>() ;
	FixedList<int,100> sl = FixedList<int,100>();
	std::cout << "list size : " << l.max_size() << "\n";
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "error: list should be empty\n";
	}
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "error: SList should be empty\n";
	}
	for (int i = 0 ; i < 4; ++i){
		l.push_back(i);
		sl.push_back(i);
	}
	std::cout << "list size : " << l.size() << "\n";
	std::cout << "list size : " << sl.size() << "\n";
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (int i = 0 ; i < 4; ++i){
		l.push_front(i * 3);
		sl.push_front(i * 3);
	}
	std::cout << "list size : " << l.size() << "\n";
	std::cout << "list size : " << sl.size() << "\n";
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator first = l.begin();
	++first;
	FixedList<int,100>::iterator firstl = sl.begin();
	++firstl;

	
	l.erase(first);
	sl.erase(firstl);
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	for (int i = 0 ; i < 4; ++i){
		l.push_front(i * 15);
		sl.push_front(i * 15);
	}
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (int i = 0 ; i < 3; ++i){
		sl.pop_back();
		l.pop_back();
	}
		std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator l_it = l.begin();
	++l_it;++l_it;++l_it;
	FixedList<int,100>::iterator sl_it = sl.begin();
	++sl_it;++sl_it;++sl_it;
	
	while (l_it != l.end() ){
		l_it = l.erase(l_it);
	
	}
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	while (sl_it != sl.end() ){
		sl_it = sl.erase(sl_it);//bug here: ..tail pointer is messed up
	
	}
	std::cout << "------------------------------" << std::endl;
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	l.erase(l_it, l.end());
	sl.erase(sl_it, sl.end());

	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator it_second_place = l.begin();
	++it_second_place;
	++it_second_place;
	int n = 5;
	for (int i = 0 ; i < n; ++i){
		it_second_place = l.insert(it_second_place,i);
	}
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	FixedList<int,100>::iterator it_sl_second_place = sl.begin();
	++it_sl_second_place;
	++it_sl_second_place;
	for (int i = 0 ; i < n; ++i){
		it_sl_second_place = sl.insert(it_sl_second_place,i);
	}
	
	std::cout << "------------------------------" << std::endl;
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator it_third_place = l.begin();
	++it_third_place;
	++it_third_place;
	//n = 5;
	
	l.insert(it_third_place,4,19);
	
	FixedList<int,100>::iterator it_sl_third_place = sl.begin();
	++it_sl_third_place;
	++it_sl_third_place;

	sl.insert(it_sl_third_place,(SList<int>::size_type)4,19);
	
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	for (int i = 0 ; i < 3; ++i){
		sl.pop_back();
		l.pop_back();
	}

	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
//	for (SList<int>::iterator it = )
	std::list<int>::iterator ret1 = l.insert(l.end(), 37);
	auto ret2 = sl.insert(sl.end(), 37);

	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	l.insert(ret1, 39);
	sl.insert(ret2,39);
	
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (auto it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

}
void SListVecTest()
{
	using namespace unstd;
	std::list<int> l = std::list<int>() ;
	SListVec<int> sl = SListVec<int>();
	std::cout << "list size : " << l.max_size() << "\n";
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "error: list should be empty\n";
	}
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "error: SList should be empty\n";
	}
	for (int i = 0 ; i < 4; ++i){
		l.push_back(i);
		sl.push_back(i);
	}
	std::cout << "list size : " << l.size() << "\n";
	std::cout << "list size : " << sl.size() << "\n";
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (int i = 0 ; i < 4; ++i){
		l.push_front(i * 3);
		sl.push_front(i * 3);
	}
	std::cout << "list size : " << l.size() << "\n";
	std::cout << "list size : " << sl.size() << "\n";
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator first = l.begin();
	++first;
	SListVec<int>::iterator firstl = sl.begin();
	++firstl;

	
	l.erase(first);
	sl.erase(firstl);
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	for (int i = 0 ; i < 4; ++i){
		l.push_front(i * 15);
		sl.push_front(i * 15);
	}
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	for (int i = 0 ; i < 3; ++i){
		sl.pop_back();
		l.pop_back();
	}
		std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator l_it = l.begin();
	++l_it;++l_it;++l_it;
	SListVec<int>::iterator sl_it = sl.begin();
	++sl_it;++sl_it;++sl_it;
	
	while (l_it != l.end() ){
		l_it = l.erase(l_it);
	
	}
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	while (sl_it != sl.end() ){
		sl_it = sl.erase(sl_it);//bug here: ..tail pointer is messed up
	
	}
	std::cout << "------------------------------" << std::endl;
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	l.erase(l_it, l.end());
	sl.erase(sl_it, sl.end());

	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator it_second_place = l.begin();
	++it_second_place;
	++it_second_place;
	int n = 5;
	for (int i = 0 ; i < n; ++i){
		it_second_place = l.insert(it_second_place,i);
	}
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	SListVec<int>::iterator it_sl_second_place = sl.begin();
	++it_sl_second_place;
	++it_sl_second_place;
	for (int i = 0 ; i < n; ++i){
		it_sl_second_place = sl.insert(it_sl_second_place,i);
	}
	
	std::cout << "------------------------------" << std::endl;
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	std::list<int>::iterator it_third_place = l.begin();
	++it_third_place;
	++it_third_place;
	//n = 5;
	
	l.insert(it_third_place,4,19);
	
	SListVec<int>::iterator it_sl_third_place = sl.begin();
	++it_sl_third_place;
	++it_sl_third_place;

	sl.insert(it_sl_third_place,(SList<int>::size_type)4,19);
	
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	for (int i = 0 ; i < 3; ++i){
		sl.pop_back();
		l.pop_back();
	}

	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
//	for (SList<int>::iterator it = )
	std::list<int>::iterator ret1 = l.insert(l.end(), 37);
	auto ret2 = sl.insert(sl.end(), 37);

	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}

	l.insert(ret1, 39);
	sl.insert(ret2,39);
	
	std::cout << "------------------------------" << std::endl;
	for (std::list<int>::iterator it = l.begin() ; it != l.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
	std::cout << "------------------------------" << std::endl;
	for (SListVec<int>::iterator it = sl.begin() ; it != sl.end(); ++it){
		std::cout << "val " << *it << std::endl;
	}
}
#include "BigIntBasicTest.h"
class foo{};
void main (int argc, char* argv){

	FixedListTest();
	/*BigInteger fuf("-1754353424323554354352235532");
	std::cout << fuf << std::endl;
	BigInteger limit("4324234234324432432432432432453656554432343243267868767");
	BigInteger divisor("4324234342234");
	for (BigInteger i ("342425234454353452324234234234") ; i < limit ; i*=11){
		divisor +=17;
		BigInteger quot = BigInteger(i) / divisor;
		BigInteger res = BigInteger(i) % divisor;
		BigInteger inverse = ((quot * divisor ) + res);
		std::cout << BigInteger(i) << " = " << quot << " * " <<divisor <<"  + " <<  res << " ( " <<  inverse<< " )" <<std::endl;
		assert(inverse == BigInteger(i));
	}*/
//	foo *f = Singleton<foo>::getInstance(); 
//#define DEVIS_TEST
#ifdef DEVIS_TEST
	big::StringTest();
	big::FibonacciTest();
	big::FactorialTest();
	big::ShiftTest();
	big::SignTest();
#endif
	//WaterCalcTest(argc, argv);
	//BigIntegerTest();
	//SListTest();
//	SListInterfaceTest();
	//SListVecTest();
	while(true){}
}